# #借助map和reduce函数写一个str2int的函数

# from functools import reduce

# DIGITS = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}

# def str2int(s):
#     def fn(x,y):
#         return x*10+y
#     def char2num(s):
#         return DIGITS[s]
#     return reduce(fn,map(char2num,s))
# print(DIGITS['1'])


# #利用map()函数，把用户输入的不规范的英文名字，变为首字母大写，其他小写的规范名字。输入：['adam', 'LISA', 'barT']，输出：['Adam', 'Lisa', 'Bart']：
def normalize(name):
    #还可以添加上对name为空的判断
    if len(name) == 0:
        raise ValueError('英文名不能为空！')
    return name[0].upper() + name[1:].lower() #字符串是不可变对象 不能通过索引直接进行修改


# # 测试:
# L1 = ['adam', 'LISA', 'barT']
# L2 = list(map(normalize, L1))
# print(L2)



# #Python提供的sum()函数可以接受一个list并求和，请编写一个prod()函数，可以接受一个list并利用reduce()求积：
# from functools import reduce

# def prod(L):
#     def mul(x,y):
#         return x * y
#     return reduce(mul,L)

# print('3 * 5 * 7 * 9 =', prod([3, 5, 7, 9]))
# if prod([3, 5, 7, 9]) == 945:
#     print('测试成功!')
# else:
#     print('测试失败!')



# #利用map和reduce编写一个str2float函数，把字符串'123.456'转换成浮点数123.456：
# from functools import reduce

# def str2float(s):
#     DIGITS = {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}
#     def char2num(s):
#         return DIGITS[s]
#     def fx(x,y):
#         return x * 10 + y
#     # i = 0
#     # while s[i] != '.':
#     #     i = i + 1
#     #可以定义一个函数来寻找小数点位置
#     def finddot(str):
#         for i in range(len(str)):
#             if str[i] == '.':
#                 break
#         return i
#     i = finddot(s)
#     s1 = s[:i]
#     s2 = s[i+1:]
#     return reduce(fx,map(char2num,s1)) + (reduce(fx,map(char2num,s2)))/(10**(len(s2)))

# print('str2float(\'123.456\') =', str2float('123.456'))
# if abs(str2float('123.456') - 123.456) < 0.00001:
#     print('测试成功!')
# else:
#     print('测试失败!')



# def isodd(n):
#     return n % 2 == 1
# print(list(filter(isodd,[1,2,4,5,8,9])))



# #素数生成器
# #先构造奇数生成器
# def _odd_iter():
#     n = 1
#     while True:
#         n = n + 2
#         yield n

# def _not_divisible(n):
#     return lambda x : x % n > 0#返回一个判断参数能不能被n整除的函数

# #定义一个素数生成器
# def primes():
#     yield 2
#     it = _odd_iter()  #初始序列
#     while True:
#         n = next(it) #返回序列的第一个数
#         yield n
#         it = filter(_not_divisible(n),it) #构造新序列

# #打印1000以内的素数
# for n in primes():
#     if n < 100:
#         print(n)
#     else:
#         break



# #回数是指从左向右读和从右向左读都是一样的数，例如12321，909。请利用filter()筛选出回数：


# # #用字符串方式来判断
# # def is_palindrome(n):
# #     # s = str(n)
# #     # return s == s[::-1]
# #     #更精简的写法
# #     return str(n) == str(n)[::-1]

# #通过计算来判断
# def is_palindrome(n):
#     t = n
#     r = 0
#     while n != 0:
#         r = r * 10 + n % 10
#         n = n // 10
#     return r == t

# # 测试:
# output = filter(is_palindrome, range(1, 1000))
# print('1~1000:', list(output))
# if list(filter(is_palindrome, range(1, 200))) == [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 101, 111, 121, 131, 141, 151, 161, 171, 181, 191]:
#     print('测试成功!')
# else:
#     print('测试失败!')





#对一组tuple组成的list进行排序

# #按名字排序
#L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]
# def by_name(t):
#     return t[0]

# L2 = sorted(L, key=by_name)
# print(L2)

# #按成绩降序排序
# L = [('Bob', 75), ('Adam', 92), ('Bart', 66), ('Lisa', 88)]

# def by_score(t):
#     return -t[1]
#     #函数是作用于list的元素上的 即作用于tuple上 对列表L中的每个元素（也就是每个元组）调用by_score函数
#     # t[0]表示元组中的第一个元素即字符串，t[1]表示元组中的第二个元素即数字

# L2 = sorted(L, key=by_score)
# print(L2)



# def inc():
#     x = 0
#     def fn():
#         nonlocal x
#         x = x + 1
#         return x
#     return fn

# f = inc()
# print(f()) # 1
# print(f()) # 2



#利用闭包返回一个计数器函数，每次调用它返回递增整数：
# def createCounter():
#     x = 0
#     def counter():
#         nonlocal x
#         x = x +1
#         return x
#     return counter

# #评论区解法
# def createCounter():
#     count = [0]  # 用列表保存可变状态
#     def counter():
#         count[0] += 1  # 修改列表元素的值
#         return count[0]
#     return counter

# # 测试:
# counterA = createCounter()
# print(counterA(), counterA(), counterA(), counterA(), counterA()) # 1 2 3 4 5
# counterB = createCounter()
# if [counterB(), counterB(), counterB(), counterB()] == [1, 2, 3, 4]:
#     print('测试通过!')
# else:
#     print('测试失败!')


# #使用匿名函数简化代码

# L = list(filter(lambda x:x % 2, range(1, 20)))

# print(L)



# #装饰器 decorator
# #如果需要传入参数 则装饰器需要在嵌套一层 如下
# import functools
# def log(text):
#     def decorator(func):
#         @functools.wraps(func)  #此代码的作用是把原始函数的__name__等属性复制到wrapper()函数中
#         def wrapper(*args,**kw):
#             print('%s %s():' % (text,func.__name__))
#             return func(*args,**kw)
#         return wrapper
#     return decorator
# @log('execute')  #等同于 now = log('execute')(now)

# def now():
#     print('2025-07-04')
# now()
# print(now.__name__)




# #练习 请设计一个decorator，它可作用于任何函数上，并打印该函数的执行时间：
# import time, functools

# def metric(fn):
#     @functools.wraps(fn)
#     def wrapper(*args,**kw):
#         start_time = time.time()
#         ret = fn(*args,**kw)
#         end_time = time.time()
#         print('%s executed in %.8s ms' % (fn.__name__, end_time-start_time))
#         return ret
#     return wrapper

# # 测试
# @metric
# def fast(x, y):
#     time.sleep(0.0012)
#     return x + y;

# @metric
# def slow(x, y, z):
#     time.sleep(0.1234)
#     return x * y * z;

# f = fast(11, 22)
# s = slow(11, 22, 33)
# if f != 33:
#     print('测试失败!')
# elif s != 7986:
#     print('测试失败!')



# #请编写一个decorator，能在函数调用的前后打印出'begin call'和'end call'的日志。
# import functools
# def info(func):
#     @functools.wraps(func)
#     def wrapper(*args,**kw):
#         print('begin call %s():' % func.__name__)
#         ret = func(*args,**kw)
#         print('end call %s():' % func.__name__)
#         return ret
#     return wrapper

# @info
# def test():
#     print('executed!')
# test()


#能否写出一个@log的decorator，使它既支持：@log 又支持：@log('execute')
# import functools
# def log(text):
#     def decorator(func):
#         @functools.wraps(func)
#         def wrapper(*args,**kw):
#             if isinstance(text,str):
#                 print('%s %s():' % (text,func.__name__))
#                 ret = func(*args,**kw)
#             else:
#                 print('call %s()' % func.__name__)
#                 ret = func(*args,**kw)
#                 print('end_call %s()' % func.__name__)
#             return ret
#         return wrapper
#     if isinstance(text,str): #当text是字符串时 说明要使用的是@log('text')，返回 decorator，返回装饰器函数，之后这个装饰器函数会接收被装饰的函数。
#         return decorator
#     else:
#         return decorator(text)#当text不是字符串时，说明text是函数名，返回 decorator(arg)，就相当于直接把装饰器应用到函数上。

# @log
# def fn1():
#     print('Nothing to do1')
# @log('execute')
# def fn2():
#     print('Nothing to do2')
# fn1()
# fn2()


#ai写的代码参考
def log(arg=None):#arg默认为空
    def decorator(func):
        def wrapper(*args, **kwargs):
            if callable(arg):
                # 不带参数的情况，arg是被装饰的函数
                print(f'begin call {arg.__name__}')
                result = arg(*args, **kwargs)
                print(f'end call {arg.__name__}')
            else:
                # 带参数的情况，arg是传入的字符串
                print(f'{arg} {func.__name__}()')
                result = func(*args, **kwargs)
            return result
        return wrapper
    if callable(arg):
        # 不带参数时，直接应用装饰器
        return decorator(arg)
    else:
        # 带参数时，返回装饰器函数
        return decorator

# 测试代码
@log
def test1():
    pass

@log('execute')
def test2():
    pass

test1()
test2()